package com.cloud.alibaba.common.util;

import com.cloud.alibaba.common.util.entity.DataTimeRange;
import com.google.common.collect.Lists;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public class DateUtil {


    public static LocalDateTime date2LocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date getDate(int year, int month, int day, int hour, int minute, int second) {
        LocalDateTime localDayStartTime = LocalDateTime.of(year, month, day, hour, minute, second);
        return localDateTime2Date(localDayStartTime);
    }

    public static String getDateTimeString(Date date, String formatter) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatter);
        return dateTimeFormatter.format(date2LocalDateTime(date));
    }

    public static String getDateTimeString(Date date) {
        return getDateTimeString(date, "yyyy-MM-dd HH:mm:ss");
    }

    public static String getDateString(Date date) {
        return getDateTimeString(date, "yyyy-MM-dd");
    }

    public static Date getDateFromString(String date, String formatter) {
        Date tempDate = null;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatter);
        try {
            tempDate = simpleDateFormat.parse(date);
        } catch (ParseException parseException) {
            parseException.printStackTrace();
        }
        return tempDate;
    }

    public static Date getDateFromString(String date) {
        return getDateFromString(date, "yyyy-MM-dd HH:mm:ss");
    }

    public static Date changeDateFormatter(Date originDate, String formatter) {
        return DateUtil.getDateFromString(DateUtil.getDateTimeString(originDate, formatter), formatter);
    }

    public static Date plusHours(Date date, long hours) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        LocalDateTime resultTime = localDateTime.plusHours(hours);
        return localDateTime2Date(resultTime);
    }


    /**
     * 获取指定日期的开始时间
     *
     * @param date
     * @return
     */
    public static Date getDateStartTime(Date date) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        int year = localDateTime.getYear();
        int month = localDateTime.getMonthValue();
        int day = localDateTime.getDayOfMonth();
        return localDateTime2Date(LocalDateTime.of(year, month, day, 0, 0, 0));
    }

    public static Date getDateEndTime(Date date) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        int year = localDateTime.getYear();
        int month = localDateTime.getMonthValue();
        int day = localDateTime.getDayOfMonth();
        return localDateTime2Date(LocalDateTime.of(year, month, day, 23, 59, 59));
    }

    /**
     * 获取指定日期的当月开始时间
     *
     * @param date
     * @return
     */
    public static Date getMonthStartTime(Date date) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        int year = localDateTime.getYear();
        int month = localDateTime.getMonthValue();
        return localDateTime2Date(LocalDateTime.of(year, month, 1, 0, 0, 0));
    }


    /**
     * 获取指定日期的开始时间和结束时间
     *
     * @param date
     * @return
     */
    public static List<Date> getDayStartAndEndTime(Date date) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        int year = localDateTime.getYear();
        int month = localDateTime.getMonthValue();
        int day = localDateTime.getDayOfMonth();
        LocalDateTime localDayStartTime = LocalDateTime.of(year, month, day, 0, 0, 0);
        LocalDateTime localDayEndTime = LocalDateTime.of(year, month, day, 23, 59, 59);
        return Arrays.asList(localDateTime2Date(localDayStartTime), localDateTime2Date(localDayEndTime));
    }


    /**
     * 获取指定日期之前天数的日期
     *
     * @param date
     * @param days
     * @return
     */
    public static Date getDateBefore(Date date, long days) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        return localDateTime2Date(localDateTime.minusDays(days));
    }

    /**
     * 获取指定日期之后天数的日期
     *
     * @param date
     * @param days
     * @return
     */
    public static Date getDateAfter(Date date, long days) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        return localDateTime2Date(localDateTime.plusDays(days));
    }

    /**
     * 获取昨天的开始和结束时间
     *
     * @return
     */
    public static List<Date> getYesterdayStartAndEndTime() {
        return getDayStartAndEndTime(getDateBefore(new Date(), 1));
    }

    /**
     * 获取指定日期所在月份的开始和结束时间
     *
     * @param date
     * @return
     */
    public static List<Date> getMonthStartAndEndTime(Date date) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        LocalDateTime localMonthStartTime = LocalDateTime.of(localDateTime.getYear(),
                localDateTime.getMonth(), 1, 0, 0, 0);
        //当月结束时间：下个月第一天的开始时间减去一秒钟
        LocalDateTime localMonthEndTime = localMonthStartTime.plusMonths(1).minusSeconds(1);
        return Arrays.asList(localDateTime2Date(localMonthStartTime), localDateTime2Date(localMonthEndTime));
    }

    /**
     * 获取上周的开始时间和结束时间
     *
     * @param date
     * @return
     */
    public static List<Date> getLastWeekStartAndEndTime(Date date) {
        List<Date> lastWeekStartAndEndTime = Lists.newArrayList();
        LocalDateTime localDateTime = date2LocalDateTime(date);
        LocalDateTime localMondayLastWeek = LocalDateTime.of(localDateTime.getYear(), localDateTime.getMonth(), localDateTime.getDayOfMonth(), 0, 0, 0).minusWeeks(1l).with(DayOfWeek.MONDAY);

        LocalDateTime localSundayLastWeek = localMondayLastWeek.plusDays(7).minusSeconds(1);

        Date mondayLastWeek = localDateTime2Date(localMondayLastWeek);
        Date sundayLastWeek = localDateTime2Date(localSundayLastWeek);

        lastWeekStartAndEndTime.add(mondayLastWeek);
        lastWeekStartAndEndTime.add(sundayLastWeek);
        return lastWeekStartAndEndTime;
    }


    /**
     * 获取指定日期年份
     *
     * @param date
     * @return
     */
    public static int getDateYear(Date date) {
        return date2LocalDateTime(date).getYear();
    }

    /**
     * 获取当前年份
     *
     * @return
     */
    public static int getCurrentYear() {
        return getDateYear(new Date());
    }

    /**
     * 获取指定日期月份
     *
     * @param date
     * @return
     */
    public static int getDateMonth(Date date) {
        return date2LocalDateTime(date).getMonthValue();
    }

    /**
     * 获取当前月份
     *
     * @return
     */
    public static int getCurrentMonth() {
        return getDateMonth(new Date());
    }

    /**
     * 获取指定日期的年月
     *
     * @param date
     * @return
     */
    public static String getDateYearMonth(Date date) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        return localDateTime.getYear() + "-" + localDateTime.getMonthValue();
    }


    /**
     * 获取指定日期的年月日
     *
     * @param date
     * @return
     */
    public static String getDateYearMonthDay(Date date) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        return localDateTime.getYear() + "-" + localDateTime.getMonthValue() + "-" + localDateTime.getDayOfMonth();
    }

    /**
     * 获取指定年份的开始结束时间
     *
     * @param year
     * @return
     */
    public static List<Date> getYearStartAndEndTime(int year) {
        Date startTime = getDate(year, 1, 1, 0, 0, 0);
        Date endTime = getDate(year, 12, 31, 23, 59, 59);
        return Arrays.asList(startTime, endTime);
    }

    /**
     * 获取指定年份的开始结束时间
     *
     * @param date
     * @return
     */
    public static List<Date> getYearStartAndEndTime(Date date) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        return getYearStartAndEndTime(localDateTime.getYear());
    }


    /**
     * d1<d2
     *
     * @param d1
     * @param d2
     * @return
     */
    public static boolean lt(Date d1, Date d2) {
        return d1.compareTo(d2) < 0;
    }

    /**
     * d1>d2
     *
     * @param d1
     * @param d2
     * @return
     */
    public static boolean gt(Date d1, Date d2) {
        return d1.compareTo(d2) > 0;
    }

    /**
     * d1<=d2
     *
     * @param d1
     * @param d2
     * @return
     */
    public static boolean lte(Date d1, Date d2) {
        return d1.compareTo(d2) <= 0;
    }

    /**
     * d1>=d2
     * -d1
     *
     * @param d1
     * @param d2
     * @return
     */
    public static boolean gte(Date d1, Date d2) {
        return d1.compareTo(d2) >= 0;
    }

    public static boolean eq(Date d1, Date d2) {
        return d1.compareTo(d2) == 0;
    }


    /**
     * 2个时间间隔的小时数
     *
     * @param d1
     * @param d2
     * @return
     */
    public static int periodHours(Date d1, Date d2) {
        return (int) ((d2.getTime() - d1.getTime()) / (1000 * 60 * 60));
    }

    public static List<DataTimeRange> getRangeList(Date begin, Date end) {
        long beginTime = begin.getTime();
        long endTime = end.getTime();
        long range = endTime - beginTime;
        long size = range / (1000 * 60 * 60);
        List<DataTimeRange> dataTimeRanges = new ArrayList<>();
        LocalDateTime endDateTime = date2LocalDateTime(end);
        LocalDateTime beginDateTime = date2LocalDateTime(begin);
        for (int i = 0; i < size; i++) {
            DataTimeRange dataTimeRange = new DataTimeRange();
            LocalDateTime localDateTime1 = beginDateTime.plusHours(i);
            LocalDateTime localDateTime2 = beginDateTime.plusHours(i + 1);
            if (localDateTime2.isBefore(endDateTime)) {
                Date rangeBegin = localDateTime2Date(localDateTime1);
                Date rangeEnd = localDateTime2Date(localDateTime2);
                dataTimeRange.setStart(rangeBegin);
                dataTimeRange.setEnd(rangeEnd);
                dataTimeRanges.add(dataTimeRange);
            }
        }
        return dataTimeRanges;
    }

    //当前时间转换到小时
    public static Date getHourTimeFormat(Date date){
        LocalDateTime time = date2LocalDateTime(date);
        return getDate(time.getYear(),time.getMonthValue(),time.getDayOfMonth(),time.getHour(),0,0);
    }


}
